package org.bonorsoft.modules.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.bonorsoft.common.api.vo.Result;
import org.bonorsoft.common.constant.CacheConstant;
import org.bonorsoft.common.constant.CommonConstant;
import org.bonorsoft.common.constant.UserConstants;
import org.bonorsoft.common.exception.WilliamBootException;
import org.bonorsoft.common.system.api.ISysBaseAPI;
import org.bonorsoft.common.system.vo.LoginUser;
import org.bonorsoft.common.util.PasswordUtil;
import org.bonorsoft.common.util.StringUtils;
import org.bonorsoft.common.util.oConvertUtils;
import org.bonorsoft.modules.system.entity.SysUser;
import org.bonorsoft.modules.system.mapper.SysUserMapper;
import org.bonorsoft.modules.system.service.ISysUserService;
import org.bonorsoft.modules.sysutils.login.LoginInfo;
import org.bonorsoft.modules.user.entity.Params;
import org.bonorsoft.modules.user.service.ISysUserRoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * @Description: 用户信息
 * @Author: jeecg-boot
 * @Date:   2020-08-20
 * @Version: V1.0
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ISysBaseAPI sysBaseAPI;

    @Autowired
    private ISysUserRoleService userRoleService;

    @Override
    public SysUser getUserByName(String username) {
        return userMapper.getUserByName(username);
    }

    /**
     * 根据手机号获取用户
     * @param phone
     * @return
     */
    @Override
    public SysUser getUserByPhone(String phone) {
        return this.getOne(new QueryWrapper<SysUser>().eq("phone", phone));
    }

    /**
     * 登录微信小程序
     * @param sysUser
     * @param phone
     * @return
     */
    @Override
    public Result checkUserIsEffectiveWithWx(SysUser sysUser, String phone) {
        Result<JSONObject> result = new Result<>();
        //情况1：根据用户信息查询，该用户不存在
        if (sysUser == null) {
            JSONObject obj = new JSONObject();
            obj.put("phone", phone);
            result.setResult(obj);
            result.error500("该用户不存在");
            sysBaseAPI.addLog("用户登录微信小程序失败，手机号码不存在！", CommonConstant.LOG_TYPE_1, null);
            return result;
        }
        //情况2：根据用户信息查询，该用户已注销
        if (CommonConstant.DEL_FLAG_1.equals(sysUser.getDelFlag())) {
            sysBaseAPI.addLog("用户登录微信小程序失败，用户名:" + sysUser.getUsername() + "已注销！", CommonConstant.LOG_TYPE_1, null);
            result.error500("该用户已注销");
            return result;
        }
        //情况3：根据用户信息查询，该用户已冻结
        if (CommonConstant.USER_FREEZE.equals(sysUser.getStatus())) {
            sysBaseAPI.addLog("用户登录微信小程序失败，用户名:" + sysUser.getUsername() + "未启用！", CommonConstant.LOG_TYPE_1, null);
            result.error500("该用户未启用，请联系管理员");
            return result;
        }
        return result;
    }

    /**
     * 校验用户是否有效
     * @param sysUser
     * @return
     */
    @Override
    public Result checkUserIsEffective(SysUser sysUser) {
        Result<?> result = new Result<Object>();
        //情况1：根据用户信息查询，该用户不存在
        if (sysUser == null) {
            result.error500("该用户不存在，请注册");
            sysBaseAPI.addLog("用户登录失败，用户不存在！", CommonConstant.LOG_TYPE_1, null);
            return result;
        }
        //情况2：根据用户信息查询，该用户已注销
        if (CommonConstant.DEL_FLAG_1.equals(sysUser.getDelFlag())) {
            sysBaseAPI.addLog("用户登录失败，用户名:" + sysUser.getUsername() + "已注销！", CommonConstant.LOG_TYPE_1, null);
            result.error500("该用户已注销");
            return result;
        }
        //情况3：根据用户信息查询，该用户已冻结
        if (CommonConstant.USER_FREEZE.equals(sysUser.getStatus())) {
            sysBaseAPI.addLog("用户登录失败，用户名:" + sysUser.getUsername() + "未启用！", CommonConstant.LOG_TYPE_1, null);
            result.error500("该用户未启用，请联系管理员");
            return result;
        }
        return result;
    }

    @Override
    @CacheEvict(value= {CacheConstant.SYS_USERS_CACHE}, key="#username")
    public void updateUserDepart(String username, Long deptId) {
        baseMapper.updateUserDepart(username, deptId);
    }

    @Override
    public List<String> getAllMenuUser(Long menuId) {
        return userMapper.getAllMenuUser(menuId);
    }

    @Override
    public List<String> getAllRoleUser(String roleId) {
        return userMapper.getAllRoleUser(roleId);
    }

    @Override
    public IPage<SysUser> selectUser(Page<SysUser> page, SysUser sysUser, Params params, HttpServletRequest request) {
        String sql = (String) request.getAttribute(CommonConstant.DATA_SCOPE);
        return userMapper.selectUser(page,sysUser,params, sql);
    }

    /**
     * 根据角色id查询用户
     * @param page
     * @param user
     * @param req
     * @return
     */
    @Override
    public IPage<SysUser> pageByConditions(Page<SysUser> page, SysUser user, HttpServletRequest req) {
        String roleId = req.getParameter("roleId");
        String sql = (String) req.getAttribute(CommonConstant.DATA_SCOPE);
        return userMapper.pageByConditions(page,user,roleId,sql);
    }

    @Override
    public int checkDeptExistUser(Long deptId) {
        return this.count(new QueryWrapper<SysUser>()
                .eq("del_flag", "0")
                .eq("dept_id", deptId));
    }

    /**
     * 校验用户名称是否唯一
     *
     * @param username 登录名称
     * @return 结果
     */
    @Override
    public String checkUserNameUnique(String username) {
        int count = this.count(new QueryWrapper<SysUser>().eq("username", username));
        if (count > 0)
        {
            return UserConstants.USER_NAME_NOT_UNIQUE;
        }
        return UserConstants.USER_NAME_UNIQUE;
    }

    /**
     * 校验手机号码是否唯一
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public String checkPhoneUnique(SysUser user) {
        String userId = StringUtils.isNull(user.getId()) ? "-1" : user.getId();
        SysUser info = checkPhoneUnique(user.getPhone(), null);
        if (StringUtils.isNotNull(info) && !info.getId().equals(userId))
        {
            return UserConstants.USER_PHONE_NOT_UNIQUE;
        }
        return UserConstants.USER_PHONE_UNIQUE;
    }

//    /**
//     * 校验email是否唯一
//     *
//     * @param user 用户信息
//     * @return 结果
//     */
//    @Override
//    public String checkEmailUnique(SysUser user) {
//        String userId = StringUtils.isNull(user.getId()) ? "-1" : user.getId();
//        SysUser info = checkPhoneUnique(null, user.getEmail());
//        if (StringUtils.isNotNull(info) && !info.getId().equals(userId))
//        {
//            return UserConstants.USER_EMAIL_NOT_UNIQUE;
//        }
//        return UserConstants.USER_EMAIL_UNIQUE;
//    }

    /**
     * 根据条件获取用户信息
     * @param phone
     * @return
     */
    private SysUser checkPhoneUnique(String phone, String email) {
        return this.getOne(new QueryWrapper<SysUser>()
                .eq(phone != null, "phone", phone)
                .eq(email != null, "email", email).select("id", "phone", "email"));
    }

    /**
     * 添加用户信息
     * @param user 实体对象
     * @return
     */
    @Override
    @Transactional
    public boolean save(SysUser user, String[] roleIds) {
        user.setCreateTime(new Date());//设置创建时间
        user.setCreateBy(LoginInfo.getLoginUser().getUsername());
        String salt = oConvertUtils.randomGen(8);
        user.setSalt(salt);
        String passwordEncode = PasswordUtil.encrypt(user.getUsername(), user.getPassword(), salt);
        user.setPassword(passwordEncode);
        user.setStatus(CommonConstant.USER_UNFREEZE);
        user.setDelFlag(CommonConstant.DEL_FLAG_0);
        boolean isSuccess = retBool(baseMapper.insert(user));
        // 新增用户与角色管理
        userRoleService.insertUserRole(user.getId(), roleIds);
        return isSuccess;
    }

    /**
     * 小程序 群众用户注册（无部门）
     * @param user
     * @return
     */
    @Override
    public boolean add(SysUser user,String[] roleIds) {
        user.setCreateTime(new Date());
        user.setCreateBy(user.getUsername());
        String salt = oConvertUtils.randomGen(8);
        user.setSalt(salt);
        String passwordEncode = PasswordUtil.encrypt(user.getUsername(), user.getPassword(), salt);
        user.setPassword(passwordEncode);
        user.setStatus(CommonConstant.USER_UNFREEZE);
        user.setDelFlag(CommonConstant.DEL_FLAG_0);
        boolean isSuccess = retBool(baseMapper.insert(user));
        userRoleService.insertUserRole(user.getId(),roleIds);
        return isSuccess;
    }


    /**
     *
     * 校验用户是否允许操作
     * @param user 用户信息
     */
    @Override
    public void checkUserAllowed(SysUser user) {
        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(user, loginUser);
        if (StringUtils.isNotNull(user.getId()) && loginUser.ifAdmin())
        {
            throw new WilliamBootException("不允许操作超级管理员用户");
        }
    }

    /**
     * 编辑用户信息
     * @param user 用户信息
     * @return
     */
    @Override
    @Transactional
    public boolean updateUser(SysUser user, String[] roleIds) {
        // 删除用户与角色关联
        userRoleService.deleteUserRoleByUserId(user.getId());
        // 新增用户与角色管理
        userRoleService.insertUserRole(user.getId(), roleIds);
        user.setUpdateBy(LoginInfo.getLoginUser().getUsername());
        user.setUpdateTime(new Date());
        return this.updateById(user);
    }

    /**
     * 删除（根据ID 批量删除）
     * @param idList 主键ID列表
     * @return
     */
    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        idList.forEach(item -> checkUserAllowed(new SysUser().setId(item.toString())));
        return baseMapper.removeByIds(idList);
    }

    @Override
    @CacheEvict(value = {CacheConstant.SYS_USERS_CACHE}, allEntries = true)
    public Result<?> changePassword(SysUser sysUser) {
        String salt = oConvertUtils.randomGen(8);
        sysUser.setSalt(salt);
        String password = sysUser.getPassword();
        String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), password, salt);
        sysUser.setPassword(passwordEncode);
        this.userMapper.updateById(sysUser);
        return Result.ok("密码修改成功!");
    }

    /**
     * 用户授权角色
     *
     * @param userId 用户ID
     * @param roleIds 角色组
     */
    @Override
    public void insertUserAuth(String userId, String[] roleIds)
    {
        // 删除用户与角色关联
        userRoleService.deleteUserRoleByUserId(userId);
        // 新增用户与角色管理
        userRoleService.insertUserRole(userId, roleIds);
    }

    /**
     *
     * @param sysUser
     * @return
     */
    @Override
    @CacheEvict(cacheNames= CacheConstant.SYS_USERS_CACHE, key="#sysUser.username")
    public boolean updateByUser(SysUser sysUser) {
        return retBool(baseMapper.updateById(sysUser));
    }

}
